use std::{sync::Arc, time::Duration};
use tokio::sync::RwLock;

use crate::gallery::Gallery;
use crate::{assist_teacher::TeacherAssist, utils::RandomGen};

#[derive(Debug, Clone)]
pub(crate) struct Student {
    name: String,
    random: RandomGen,
}

impl Student {
    pub fn new(name: impl ToString) -> Self {
        Self {
            name: name.to_string(),
            random: RandomGen::new(5..20),
        }
    }
    pub(crate) fn name(&self) -> &str {
        &self.name
    }
    pub async fn program_or_to_teacher(
        mut self,
        teacher: Arc<TeacherAssist>,
        gallery: Arc<RwLock<Gallery>>,
    ) {
        //1.随机时间编程，编程之后就去找助教
        //2.检查助教是否在睡觉，如果在睡觉，则通知。
        //3.没有睡觉，说明在忙，则检查长廊上是否有空位
        //4.有空位，则坐在椅子上等待，
        //5.没有空位，则编程，过段时间再次找助教

        let randome_study_secs = self.random.get_random_num().expect("get random fialed!");
        println!("学生 {} 准备学习 {} 秒", &self.name, randome_study_secs);
        tokio::time::sleep(Duration::from_secs(*randome_study_secs as u64)).await;
        //此处还有另一个逻辑，助教有空，则使用信号量通知助教指导学生
        println!("学生:{}学习完毕，准备去看助教有没有时间", &self.name);
        if !teacher.is_busy().await {
            println!("学生:{}准备让助教帮助", &self.name);
            teacher.assist_student(Arc::new(self)).await;
        } else if gallery.read().await.has_empty_chair() {
            gallery.write().await.site_down(Arc::new(self))
        } else {
            println!(
                "{} 同学 发现助教没时间，也没有空位置等待，只能自己在重新学习",
                &self.name
            );
            Box::pin(self.program_or_to_teacher(teacher, gallery)).await;
        }
    }
}
